var app = angular.module('DashPlayer', ['angular-flot']);

let searchURL = window.location.search.substring(1)
let jsonFile = searchURL.split('=')[1];
let format = searchURL.split('=')[0];

app.controller('DashController', ['$scope','$interval', function ($scope, $interval) {

    console.log(jsonFile, format)
    $interval(function () {}, 1);

    $scope.tileRecord = [];
    $scope.currentBitrateList=[]
    $scope.diviationThreshold = 60;

    $scope.cacheMode = 'allEdgeCache'
    /*
    一共三种
    allEdgeCache 全部在边缘
    noEdgeCache  全部在remote
    rlEdgeCache  决策
     */
    $scope.totalDelay = 0

    //$scope.IntervalOfComputeDelay = 1000 // compute delay interval
    $scope.IntervalOfDisplayDelay= 5000

    //setInterval(computeDelay, $scope.IntervalOfComputeDelay);
    //setInterval(computeTotalDelay, $scope.IntervalOfDisplayDelay);

    //// Global variables for storage
    $scope.players = [];  // Container for players, which is easy for us to operate in them.
    $scope.playerCount = 0;
    $scope.buffer_empty_flag = [];  // Flags for players, showing whether the player is frozen or not.
    $scope.lon = 90, $scope.lat = 0;  // Longitude and latitude in spherical coordinates.
    $scope.pointerX; $scope.pointerY;  // Position of mouse click
    $scope.contents = {};  // Contents from JSON file
    $scope.startupTime = new Date().getTime();  // Initialize the startup time
    $scope.totalQOE = 0;  // Compute the QoE considering all playing tiles
    $scope.totalQOE_video = 0;  // Compute the QoE considering all playing tiles in all time
    $scope.viewerQOE = 0;  // Compute the QoE considering the tiles in FOV
    $scope.contentQOE = 0;  // Compute the QoE considering the tiles in FOV with contents as well

    $scope.pause_total = 0; //Compute pause conts for video
    $scope.pause_time = 0; //Compute pause conts for video
    $scope.rebuffer_time = 0;//Rebuffer time
    $scope.lastpause_time = 0;//last stall time
    $scope.pause_flag = 0;//0:no pause or 1:pause
    $scope.rebuffer_delay = 0;//weight for rebuffer

    //write data rotal
    $scope.playerDownloadingQualitybytext = [];  // Data from monitor
    $scope.playerBufferLengthbytext = [];  // Data from monitor
    $scope.playerAverageThroughputbytext = [];  // Data from monitor
    $scope.pause_flagbytext = [];  // Data from monitor
    $scope.pause_totalbytext = [];  // Data from monitor
    $scope.rebuffer_timebytext = [];  // Data from monitor
    $scope.bitrateInfobytext=[]

    $scope.countTime = 0;
    $scope.normalizedTime = 0;  // Set the fastest media player's timeline as the normalized time
    $scope.totalThroughput = 0;  // Data from monitor
    $scope.playerBufferLength = [];  // Data from monitor
    $scope.playerAverageThroughput = [];  // Data from monitor
    $scope.playerTime = [];  // Data from monitor
    $scope.playerDownloadingQuality = [];  // Data from monitor
    $scope.playerFOVScore = [];  // Data from monitor
    $scope.playerContentScore = [];  // Data from monitor
    $scope.playerPastDownloadingQuality = [];  // Data from monitor's playerDownloadingQuality
    $scope.playerCatchUp = [];  // Data from playback controller
    $scope.playerDivation = [];  // Data from computing QoE

    $scope.playerBitrateList = [];  // Data from bitrate list
    $scope.requestList = [];  // Data from all HTTPRequests
    $scope.ssresults = {};  // Data from contents analytics CSV files

    $scope.selectedItem = {  // Save the selected media source
        type:"json",
        // value:"https://10.128.251.221:9001/CMPVP907/aframeVP907.json"
        //value:"https://localhost:9001/0929/panorama.json"
        value:"http://localhost:8080/panorama/skiing/panorama.json"
    };

    if(jsonFile && format==='json'){
        $scope.selectedItem.value = jsonFile
    }

    $scope.optionButton = "显示设置";  // Save the state of option button
    $scope.selectedRule = "FOVRule";  // Save the selected media source
    $scope.stats = [];  // Save all the stats need to put on the charts

    $scope.chartData_quality = [];  // Save the qualtiy data need to put on the charts
    $scope.chartData_buffer = [];  // Save the buffer data need to put on the charts
    $scope.chartData_throughput = [];  // Save the throughput data need to put on the charts
    $scope.chartState = {  // Save the charts' states
        quality:{
            video_0: {
                data: [], color: '#00CCBE', label: 'video_0'
            },
            video_1:{
                data: [], color: '#ffd446', label: 'video_1'
            },
            video_2:{
                data: [], color: '#FF6700', label: 'video_2'
            },
            video_3: {
                data: [], color: '#44c248', label: 'video_3'
            },
            video_4:{
                data: [], color: '#ff000a', label: 'video_4'
            },
            video_5:{
                data: [], color: '#b300ff', label: 'video_5'
            },
            audio:{
                data: [], color: '#1100ff', label: 'audio'
            }
        },
        buffer:{
            video_0: {
                data: [], color: '#00CCBE', label: 'video_0'
            },
            video_1:{
                data: [], color: '#ffd446', label: 'video_1'
            },
            video_2:{
                data: [], color: '#FF6700', label: 'video_2'
            },
            video_3: {
                data: [], color: '#44c248', label: 'video_3'
            },
            video_4:{
                data: [], color: '#ff000a', label: 'video_4'
            },
            video_5:{
                data: [], color: '#b300ff', label: 'video_5'
            },
            audio:{
                data: [], color: '#1100ff', label: 'audio'
            }
        },
        throughput:{
            video_0: {
                data: [], color: '#00CCBE', label: 'video_0'
            },
            video_1:{
                data: [], color: '#ffd446', label: 'video_1'
            },
            video_2:{
                data: [], color: '#FF6700', label: 'video_2'
            },
            video_3: {
                data: [], color: '#44c248', label: 'video_3'
            },
            video_4:{
                data: [], color: '#ff000a', label: 'video_4'
            },
            video_5:{
                data: [], color: '#b300ff', label: 'video_5'
            },
            audio:{
                data: [], color: '#1100ff', label: 'audio'
            }
        }
    };


    //// Global variables (flexible)
    $scope.mycanvas = {  // [For capturing each frame] Set the width and height of the canvases
        "width":"120",
        "height":"120"
    };
    $scope.drawmycanvas = {  // [For capturing each frame] Set the width and height of the capture pictures
        "width":"300",
        "height":"150"
    };
    $scope.requestDuration = 3000;  // [For computing total throughput] Set the duration we consider (ms)
    $scope.requestLayBack = 0;  // [For computing total throughput] Set the lay-back time for avoiding the on-going requests (ms)
    $scope.rotateRatio = 0.1148;  // [For focusing FOV] Set the ratio of rotating when switching the angle of view
    $scope.playerBufferToKeep = 6;  // [For initializing mediaplayers] Allows you to modify the buffer that is kept in source buffer in seconds
    $scope.playerStableBufferTime = 6;  // [For initializing mediaplayers] The time that the internal buffer target will be set to post startup/seeks (NOT top quality)
    $scope.playerBufferTimeAtTopQuality = 10;  // [For initializing mediaplayers] The time that the internal buffer target will be set to once playing the top quality
    $scope.playerMinDrift = 0.02;  // [For initializing mediaplayers] The minimum latency deviation allowed
    $scope.lambdaQOE = 1.0;  // [For computing QoE] Value of the quality switches constant
    $scope.miuQOE = 4.3;  // [For computing QoE] Stall weight
    $scope.omegaQOE = 4.3;  // [For computing QoE] Content weight
    $scope.qQOE = 'log';  // [For computing QoE] a mapping function that translates the bitrate of chunk to the quality perceived by the user (Linear || Log)
    $scope.a1QOE = 0.7;  // [For computing QoE] Influence of the quality of Zone 1
    $scope.a2QOE = 0.3;  // [For computing QoE] Influence of the quality of Zone 2
    $scope.a3QOE = 0.0;  // [For computing QoE] Influence of the quality of Zone 3
    $scope.content_curTile_bias = 0.1;  // [For computing QoE] bias of tiles for computing content score
    $scope.availableStreams = [  // [For setting up the media source] All the available preset media sources
        {
            name:"轻大",
            json:"http://localhost:8080/panorama/zzu/panorama.json"
        },
        {
            name:"sunset",
            json:"http://localhost:8080/panorama/sunset/panorama.json"
        },
        {
            name:"mpd supported",
            url:"https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd"
        }
        /* {
            name:"LVOD",
            json:"https://10.85.19.76:9001/0929/panorama.json",
        },
        {
            name:"SVOD",
            json:"http://222.20.77.111/processed/CMPVP907/aframeVP907.json",
        },
        {
            name:"LIVE",
            json:"http://222.20.77.111/dash/default.json",
        },
        {
            name:"BUNNY",
            url:"https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd"
        } */
    ];
    $scope.rules = ["FOVRule", "HighestBitrateRule"];  // [For setting the ABR rule] All the available preset ABR rules
    $scope.chartOptions = {  // [For printing the chart] Set up the style of the charts
        // legend指定了指示图标的样式
        legend: {
            labelBoxBorderColor: '#c65f5f',
            placement: 'outsideGrid',
            container: '#legend-wrapper',
            // labelFormatter: function (label, series) {
            //     return '<div  style="cursor: pointer;" id="' + series.type + '.' + series.id + '" onclick="legendLabelClickHandler(this)">' + label + '</div>';
            // }
        },
        series: {
            lines: {
                show: true,
                lineWidth: 2,
                shadowSize: 1,
                steps: false,
                fill: true,
            },
            points: {
                radius: 2,
                fill: true,
                show: true
            }
        },
        grid: {
            clickable: false,
            hoverable: false,
            autoHighlight: true,
            color: '#136bfb',
            backgroundColor: '#ffffff'
        },
        axisLabels: {
            position: 'left'
        },
        xaxis: {
            tickFormatter: function tickFormatter(value) {
                return $scope.players[0].convertToTimeCode(value);
            },
            tickDecimals: 0,
            color: '#136bfb',
            alignTicksWithAxis: 1
        },
        yaxis: {
            min: 0,
            tickLength: 0,
            tickDecimals: 0,
            color: '#136bfb',
            position: 'right',
            axisLabelPadding: 20,
        },
        yaxes: []
    };
    $scope.maxPointsToChart = 50;  // [For printing the chart] Set the maximum of the points printed on the charts
    $scope.IntervalOfSetNormalizedTime = 10;  // [For setting interval] Set the fastest mediaplayer's timeline as the normalized time
    $scope.IntervalOfComputetotalThroughput = 1000;  // [For setting interval] Compute total throughput according to recent HTTP requests

    $scope.IntervalOfComputeQoE = 1000;  // [For setting interval] Compute QoE
    $scope.IntervalOfUpdateStats = 100;  // [For setting interval] update the data in monitor
    $scope.IntervalOfUpdateFigures = 1000;  // [For setting interval] Show the data in figures

    $scope.IntervalOfCaptures = 300;  // [For setting interval] Capture the pictures from mediaplayers



    //// Variables and functions for UI and options
    // For setting up the media source
    /**
     * @param item  json/mpd url
     */
    $scope.setStream = function (item) {
        if(item.json){
            $scope.selectedItem.type = "json";
            $scope.selectedItem.value = item.json;
        } else {
            $scope.selectedItem.type = "url";
            $scope.selectedItem.value = item.url;
        }
    };
    $scope.changeStream = function () {
        console.log($scope.selectedItem.value.slice(-4));
        if($scope.selectedItem.value.length > 5 && $scope.selectedItem.value.slice(-4) == "json"){
            $scope.selectedItem.type = "json";
        } else {
            $scope.selectedItem.type = "url";
        }
    };

    // For setting up the ABR rule
    $scope.showoption = function () {
        if($scope.optionButton == "显示设置") {
            document.getElementById('option').style = "background-color: #e2e1e4; z-index: 1000; position: absolute;";
            $scope.optionButton = "隐藏设置";
        } else {
            document.getElementById('option').style = "display: none;";
            $scope.optionButton = "显示设置";
        }
    };


    $scope.changeABRStrategy = function (strategy) {
        //全部设置为false
        for(let i = 0; i < $scope.rules.length; i++) {
            let d = document.getElementById($scope.rules[i]);
            d.checked = false;
        }
        // 选中的策略设为true
        document.getElementById(strategy).checked = true;
        $scope.selectedRule = strategy;
    };

    // For printing the charts
    /*
    type:quality, buffer, throughput
    id: video, audio
     */
    $scope.pushData = function (id, type) {
        switch(type) {
            case "quality":
                var data = {
                    id: id,
                    data: $scope.chartState[type][id].data,
                    label: $scope.chartState[type][id].label,
                    color: $scope.chartState[type][id].color,
                    yaxis: $scope.chartData_quality.length + 1,
                    type: type
                };
                $scope.chartData_quality.push(data);
                $scope.chartOptions.yaxes.push({
                    axisLabel: data.label
                });
                break;
            case "buffer":
                var data = {
                    id: id,
                    data: $scope.chartState[type][id].data,
                    label: $scope.chartState[type][id].label,
                    color: $scope.chartState[type][id].color,
                    yaxis: $scope.chartData_buffer.length + 1,
                    type: type
                };
                $scope.chartData_buffer.push(data);
                $scope.chartOptions.yaxes.push({
                    axisLabel: data.label
                });
                break;
            case "throughput":
                var data = {
                    id: id,
                    data: $scope.chartState[type][id].data,
                    label: $scope.chartState[type][id].label,
                    color: $scope.chartState[type][id].color,
                    yaxis: $scope.chartData_throughput.length + 1,
                    type: type
                };
                $scope.chartData_throughput.push(data);
                $scope.chartOptions.yaxes.push({
                    axisLabel: data.label
                });
                break;
        }
        $scope.chartOptions.legend.noColumns = Math.min($scope.chartData_quality.length, 7);
    };

    /**
     *
     * @param name      video_0/video_1/..../audio
     * @param type      quality/buffer/throughput
     * @param value     数据
     * @param time      当前时间
     */
    $scope.plotPoint = function (name, type, value, time) {
        var specificChart = $scope.chartState[type];
        if (specificChart) {
            var data = specificChart[name].data;
            data.push([time, value]);
            // 超过可显示的点之后删第一个元素
            if (data.length > $scope.maxPointsToChart) {
                //删去第一个元素
                data.splice(0, 1);
            }
        }
    };

    /**
     * 下载信息 到 txt
     */
    $scope.downloadRecord = function(){
        console.log('download record')
        let Quality = $scope.playerDownloadingQualitybytext ;  // Data from monitor
        let Buffer = $scope.playerBufferLengthbytext ;  // Data from monitor
        let Throughput = $scope.playerAverageThroughputbytext ;  // Data from monitor
        let pause_flag = $scope.pause_flagbytext ;  // Data from monitor
        let pause_total = $scope.pause_totalbytext ;  // Data from monitor
        let rebuffer_time = $scope.rebuffer_timebytext ;  // Data from monitor
        let tileRecord = $scope.tileRecord ;  // Data from monitor
        let bitrateList = $scope.bitrateInfobytext

        console.log(Quality,Buffer,Throughput,pause_flag,pause_total,rebuffer_time,tileRecord,bitrateList)

        if(Quality.length<=5){
            alert('数据量较小，记录少于5s，请继续观看')
            return
        }

        saveAs("bitrateLevel",Quality);
        saveAs("buffer",Buffer);
        saveAs("throughput",Throughput);
        //saveAs("pause_flag",pause_flag);
        saveAs("pause_total",pause_total);
        saveAs("rebuffer_time",rebuffer_time);
        saveAs("FovRecord",tileRecord);
        saveAs("bitrateInfo",bitrateList);
    }

    function saveAs(name, data) {
        const element = document.createElementNS("http://www.w3.org/1999/xhtml", "a"),
        ev = document.createEvent("MouseEvents"),
        urlObject = window.URL || window.webkitURL || window,
        export_blob = new Blob(data, {type: 'text/plain'});
        element.href = urlObject.createObjectURL(export_blob);
        element.download = name;
        ev.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
        element.dispatchEvent(ev);
        urlObject.revokeObjectURL(element.href);
        element.href = '';
    }

    $scope.clearChartData_quality = function () {
        /**
         * key: quality/buffer
         * $scope.chartState[key][i].data:  video_0/video_1里面的data数组 长度清0
         */
        for (var key in $scope.chartState) {
            for (var i in $scope.chartState[key]) {
                $scope.chartState[key][i].data.length = 0;
            }
        }
    };
    /**
     * @param type   quality/buffer
     * 在不同的chartData_buffer和chartData_quality里面push数据
     */
    $scope.initChartingByMediaType = function (type) {
        var arr = $scope.chartState[type];
        for (var key in arr) {
            $scope.pushData(key, type);
        }
    };


    /**
     *
     * @param url   input框里面的url 支持json/mpd
     * @param callback   回调
     */
    function getContents(url, callback) {
        let xhr = new XMLHttpRequest();
        xhr.open("GET", url, true);
        xhr.onload = callback;
        xhr.send();
    }

    // Read json file if json is available
     $scope.openJSON = function(url) {
        $scope.players = [];
        $scope.buffer_empty_flag = [];
        $scope.playerCount = 0;
        $scope.lon = 90;
        $scope.lat = 0;
        $scope.contents = {};
        getContents(url, function() {
            // contents是json格式
            $scope.contents = JSON.parse(this.responseText);
            // 如果有ssresults的结果就加载
            if ($scope.contents.ssresults && $scope.contents.ssresults != "") {
                getContents($scope.contents.baseUrl + $scope.contents.ssresults, function() {
                    $scope.ssresults = JSON.parse(this.responseText);
                });
            }
            document.getElementById('Link').style = "display: none;";
            //链接之后显示渲染按钮
            document.getElementById('Render').style = "display: inline;";
        });
    };

    // 读取default.json
    $scope.openURLs = function(url) {
        $scope.contents = {};
        getContents('./default.json', function() {
            $scope.contents = JSON.parse(this.responseText);
            let urls = url.split(/[(\n)\n]+/);
            for (let i = 0; i < $scope.contents.face; i++) {
                for (let j = 0; j < $scope.contents.row; j++) {
                    for (let k = 0; k < $scope.contents.col; k++) {
                        $scope.contents.tiles[i][j][k].src = (i * $scope.contents.row * $scope.contents.col + j * $scope.contents.col + k) < urls.length ? urls[i * $scope.contents.row * $scope.contents.col + j * $scope.contents.col + k] : urls[urls.length - 1];
                    }
                }
            }
            document.getElementById('Link').style = "display: none;";
            document.getElementById('Render').style = "display: inline;";
        });
    }


    // Initialize the aframe page
    // Open the iframe according to the number of faces, rows and cols
    $scope.aframe_init = function() {
        if ($scope.contents == {}) {
            alert('aframe initialization failed')
            return;
        }
        // 6_1_1 , 6_3_3.html 加载html
        document.getElementById( 'frame' ).src = "./" + $scope.contents.face + "_" + $scope.contents.row + "_" + $scope.contents.col + ".html";
        $scope.lon = 90;    //经度90
        $scope.lat = 0;     //纬度0
        document.getElementById('Render').style = "display: none;";
        //渲染之后显示加载按钮
        document.getElementById('Load').style = "display: inline;";
    }



    // Pause all the players
    $scope.pause_all = function() {
        for (let i = 0; i < $scope.playerCount; i++) {
            $scope.players[i].pause();
            // console.log("Player_" + i + " pauses.");
        }
        //不一定有音频
        if ($scope.contents.audio && $scope.contents.audio != "") {
            $scope.players[$scope.playerCount].pause();
            // console.log("Audio pauses.");
        }

        document.getElementById('Pause').style = "display: none;";
        // 暂停之后显示播放按钮
        document.getElementById('Play').style = "display: inline;";
        $scope.pause_flag = 1; //pause happened
        $scope.pause_total++;
        // console.log("卡顿次数"+ $scope.pause_total);
        $scope.pause_time = new Date().getTime();
         //console.log("暂停时刻"+$scope.pause_time)

    };

    // Play all the players
    $scope.play_all = function() {
        for (let i = 0; i < $scope.playerCount; i++) {
            $scope.players[i].play();
            // console.log("Player_" + i + " plays.");
        }
        if ($scope.contents.audio && $scope.contents.audio != "") {
            $scope.players[$scope.playerCount].play();
            // console.log("Audio plays.");
        }

        //normalizedTime :  the fastest media player's timeline
        if($scope.normalizedTime>0.5){
            $scope.lastpause_time = new Date().getTime() - $scope.pause_time;
            $scope.lastpause_time = $scope.lastpause_time * 0.001;
            //console.log("上次卡顿时长"+$scope.lastpause_time);
            $scope.rebuffer_time += $scope.lastpause_time;
            // console.log("重加载时间"+$scope.rebuffer_time);
            $scope.pause_flag = 0; // pause happened
        }

        document.getElementById('Play').style = "display: none;";
        // 播放期间显示暂停按钮
        document.getElementById('Pause').style = "display: inline;";
    };

    // Triggered when any player's buffer is empty, which to stop all the players and wait for rebuffering.
    function buffer_empty_event(e) {
        $scope.buffer_empty_flag[e.info.count] = true;
        $scope.pause_all();
    }

    // Triggered when any player's buffer is loaded (again), which to start all the players when all-set.
    function buffer_loaded_event(e) {
        if ($scope.buffer_empty_flag[e.info.count] == true) {
            $scope.buffer_empty_flag[e.info.count] = false;
            for (let i = 0; i < $scope.playerCount; i++) {
                if ($scope.buffer_empty_flag[i] == true) {
                    return;
                }
            }
            //音频也会阻滞所有播放
            if ($scope.contents.audio && $scope.contents.audio != "" && $scope.buffer_empty_flag[$scope.playerCount] == true) {
                return;
            }
            $scope.play_all();
        }
    }

    // Initialize when loading the videos 也就是点击index.html的加载按钮
    $scope.initial = function() {
        $scope.initChartingByMediaType('quality');
        $scope.initChartingByMediaType('buffer');
        $scope.initChartingByMediaType('throughput');
        let video, url;

        // Video part
        for (let i = 0; i < $scope.contents.face; i++) {
            for (let j = 0; j < $scope.contents.row; j++) {
                for (let k = 0; k < $scope.contents.col; k++) {
                    //frame标签  里面呈现6_2_2.html  所以里面还有query选择器 选择video标签
                    video = document.getElementById( "frame" ).contentWindow.document.querySelector("#" + "video_" + [i * $scope.contents.row * $scope.contents.col + j * $scope.contents.col + k]);
                    //dashjs创建媒体播放器
                    $scope.players[$scope.playerCount] = new dashjs.MediaPlayer().create();

                    //url = $scope.contents.tiles[i][j][k].src;
                    url = $scope.contents.baseUrl + $scope.contents.tiles[i][j][k].src;
                    $scope.buffer_empty_flag[$scope.playerCount] = true;

                    // Don't use dash.js default rules
                    $scope.players[$scope.playerCount].updateSettings({
                        'info': {
                            'id': "video_" + [i * $scope.contents.row * $scope.contents.col + j * $scope.contents.col + k],
                            'count': $scope.playerCount,
                            'face': i,
                            'row': j,
                            'col': k,
                            'duration': $scope.contents.duration,
                            'width': $scope.contents.tiles[i][j][k].width,
                            'height': $scope.contents.tiles[i][j][k].height,
                            'location': {'x': $scope.contents.tiles[i][j][k].x, 'y': $scope.contents.tiles[i][j][k].y, 'z': $scope.contents.tiles[i][j][k].z},
                            'rotation': {'rx': $scope.contents.tiles[i][j][k].rx, 'ry': $scope.contents.tiles[i][j][k].ry, 'rz': $scope.contents.tiles[i][j][k].rz},
                            'totalThroughputNeeded': true
                        },
                        'streaming': {
                            'abr': {
                                'useDefaultABRRules': false
                            },
                            'bufferToKeep': $scope.playerBufferToKeep,
                            'stableBufferTime': $scope.playerStableBufferTime,
                            'bufferTimeAtTopQuality': $scope.playerBufferTimeAtTopQuality,
                            'fastswitchenabled': true,
                            'liveDelay': 0,
                            'liveCatchup': {
                                'enabled': true,
                                'minDrift': $scope.playerMinDrift
                            }
                        }
                    });

                    // Add my custom quality switch rule, look at FoVRule.js to know more about the structure of a custom rule
                    switch ($scope.selectedRule) {
                        case "FOVRule":
                            $scope.players[$scope.playerCount].addABRCustomRule('qualitySwitchRules', 'FOVRule', FOVRule);
                            break;
                        // case "ThroughputRule":
                        // 	$scope.players[$scope.playerCount].addABRCustomRule('qualitySwitchRules', 'MyThroughputRule', MyThroughputRule);
                        // 	break;
                        case "HighestBitrateRule":
                            $scope.players[$scope.playerCount].addABRCustomRule('qualitySwitchRules', 'HighestBitrateRule', HighestBitrateRule);
                            break;
                        case "FOVContentRule":
                            $scope.players[$scope.playerCount].addABRCustomRule('qualitySwitchRules', 'FOVContentRule', FOVContentRule);
                            break;
                        default:
                            $scope.players[$scope.playerCount].updateSettings({
                                'streaming': {
                                    'abr': {
                                        'useDefaultABRRules': true
                                    }
                                }
                            });
                            break;
                    }

                    // Turn on the event listeners and add actions for triggers
                    $scope.players[$scope.playerCount].on(dashjs.MediaPlayer.events["BUFFER_EMPTY"], buffer_empty_event);
                    $scope.players[$scope.playerCount].on(dashjs.MediaPlayer.events["BUFFER_LOADED"], buffer_loaded_event);

                    // 之前已经创建了player实例 根据拿到的mpd进行加载
                    // autoplay设置为false
                    $scope.players[$scope.playerCount].initialize(video, url, false);

                    $scope.playerBufferLength[$scope.playerCount] = $scope.players[$scope.playerCount].getBufferLength();
                    $scope.playerAverageThroughput[$scope.playerCount] = $scope.players[$scope.playerCount].getAverageThroughput("video");
                    $scope.playerTime[$scope.playerCount] = $scope.players[$scope.playerCount].time();
                    $scope.playerDownloadingQuality[$scope.playerCount] = $scope.players[$scope.playerCount].getQualityFor("video");

                    //这三个是视频特有的
                    $scope.playerFOVScore[$scope.playerCount] = NaN;
                    $scope.playerContentScore[$scope.playerCount] = NaN;
                    $scope.playerBitrateList[$scope.playerCount] = [];

                    $scope.playerCatchUp[$scope.playerCount] = false;

                    $scope.playerCount++;
                }
            }
        }

        // Audio part
        if ($scope.contents.audio && $scope.contents.audio != "") {
            let audio = document.getElementById( "frame" ).contentWindow.document.querySelector("#audio");
            $scope.players[$scope.playerCount] = new dashjs.MediaPlayer().create();
            url = $scope.contents.baseUrl + $scope.contents.audio;


            //初始化buffer都标为空
            $scope.buffer_empty_flag[$scope.playerCount] = true;

            // 最后一个是音频
            $scope.players[$scope.playerCount].updateSettings({
                'info': {
                    'id': "audio",
                    'count': $scope.playerCount,
                    'duration': $scope.contents.duration
                }
            });

            // Turn on the event listeners and add actions for triggers
            $scope.players[$scope.playerCount].on(dashjs.MediaPlayer.events["BUFFER_EMPTY"], buffer_empty_event);
            $scope.players[$scope.playerCount].on(dashjs.MediaPlayer.events["BUFFER_LOADED"], buffer_loaded_event);

            // Initializing
            $scope.players[$scope.playerCount].initialize(audio, url, false);
            $scope.playerBufferLength[$scope.playerCount] = $scope.players[$scope.playerCount].getBufferLength();;
            $scope.playerAverageThroughput[$scope.playerCount] = $scope.players[$scope.playerCount].getAverageThroughput("audio");
            $scope.playerTime[$scope.playerCount] = $scope.players[$scope.playerCount].time();
            $scope.playerDownloadingQuality[$scope.playerCount] = $scope.players[$scope.playerCount].getQualityFor("audio");
            $scope.playerCatchUp[$scope.playerCount] = false;
        }

        //开始时间是当前时间戳 也就是点击加载之后的时间戳
        $scope.startupTime = new Date().getTime();

        // Set the fastest media player's timeline as the normalized time
        setInterval(setNormalizedTime, $scope.IntervalOfSetNormalizedTime);

        // Compute total throughput according to recent HTTP requests
        setInterval(computetotalThroughput, $scope.IntervalOfComputetotalThroughput);



        // Compute QoE
        setInterval(computeQoE, $scope.IntervalOfComputeQoE);

        //getBitrateList
        //setInterval(getCurrentBitrateList, $scope.IntervalOfComputeQoE);

        //record throughput (deprecated)
        //setInterval(computeSeparateThroughput, $scope.IntervalOfComputeQoE)

        // Show the data in monitor
        setInterval(updateStats, $scope.IntervalOfUpdateStats);
        // Show the data in figures
        setInterval(updateFigures, $scope.IntervalOfUpdateFigures);


        // Capture the pictures from media players  也就是右边分块0-5
        setInterval(function () {
            for (let i = 0; i < $scope.playerCount; i++) {
                document.getElementById("capture_" + i).getContext('2d').drawImage(document.getElementById( "frame" ).contentWindow.document.querySelector("#" + "video_" + i), 0, 0, $scope.drawmycanvas.width, $scope.drawmycanvas.height);
                // img.src = canvas.toDataURL("image/png");
            }
        }, $scope.IntervalOfCaptures);

        document.getElementById('Load').style = "display: none;";
        document.getElementById('Play').style = "display: inline;";
    };

    // Set the fastest media player's timeline as the normalized time
    function setNormalizedTime() {
        $scope.normalizedTime = $scope.players[0].time();
        //找到最快的那一个作为normalizedTime
        for (let i = 0; i < $scope.playerCount; i++) {
            if ($scope.players[i].time() > $scope.normalizedTime) {
                $scope.normalizedTime = $scope.players[i].time();
            }
        }
        if ($scope.contents.audio && $scope.contents.audio != "") {
            if ($scope.players[$scope.playerCount].time() > $scope.normalizedTime) {
                $scope.normalizedTime = $scope.players[$scope.playerCount].time();
            }
        }
    }

    // function computeSeparateThroughput(){
    //     let temp = []
    //     for(let i=0;i<$scope.playerCount;i++){
    //         $scope.playerAverageThroughput[i] = $scope.players[i].getAverageThroughput("video")
    //         temp[i] = $scope.players[i].getAverageThroughput("video")
    //     }
    //
    //     $scope.playerAverageThroughputbytext.push(temp)
    //     $scope.playerAverageThroughputbytext.push('\n')
    //     console.log('separate throughput', $scope.playerAverageThroughputbytext)
    // }


    $scope.computeTotalDelay = ()=>{
        let totalTransDelay = 0
        let totalResDelay = 0
        let requestListLength = $scope.requestList.length
        let reqIdx = requestListLength - 1

        if($scope.requestList.length<=10){
            console.log('暂无请求')
            alert('请求记录少于10')
            return
        }
        console.log('HttpRequestList',$scope.requestList)
        /*
        trequest：客户端发送HTTP请求的时间点；
        tresponse：客户端接收到HTTP响应的第一个字节的时间点；
        _tfinish：客户端接收完HTTP响应的最后一个字节的时间点，即请求完成时间
         */
        while(requestListLength>0 && reqIdx>=0){

            let requestStartTime = $scope.requestList[reqIdx].trequest.getTime();
            let requestFirstResponseTime  = $scope.requestList[reqIdx].tresponse.getTime();

            let responseFinishTime = $scope.requestList[reqIdx]._tfinish.getTime();

            //响应时延 拿到响应的第一个字节到请求的时间差
            let response_delay = (requestFirstResponseTime-requestStartTime)
            totalResDelay += response_delay
            console.log(dateFormat(requestStartTime),'response delay',response_delay);

            //传输时延 (请求+下载)  全部响应完成到请求的时间差
            let transmission_delay = responseFinishTime - requestStartTime
            totalTransDelay += transmission_delay
            console.log(dateFormat(requestStartTime),'transmission delay',transmission_delay);

            reqIdx--;
        }

        totalTransDelay/=1000
        let avgTransDelay = totalTransDelay/requestListLength
        // console.log('total transmission Delay so far',totalTransDelay)
        // console.log('average transmission Delay so far',avgTransDelay)


        totalResDelay/=1000
        let avgResDelay = totalResDelay/requestListLength
        // console.log('total Response Delay so far',totalResDelay)
        // console.log('average Response Delay so far',avgResDelay)
        let tmp = []

        $scope.requestList.forEach(each=>{
            tmp.push(each)
        })

        tmp.push({
            totalResDelay,
            avgResDelay,
            totalTransDelay,
            avgTransDelay,
        })

        tmp.push({
            stallTime:$scope.rebuffer_time.toFixed(2)
        })

        console.log(tmp);


        let url = $scope.selectedItem.value
        let reg = /:([0-9]{4})/
        let port = parseInt(reg.exec(url)[1])
        console.log(port);

        let link = document.createElement('a');
        let downloadName = 'httpRequest.json'
        switch (port){
            case 8080:
                downloadName = 'allCache.json'
                break;
            case 9974:
                downloadName = 'partCache.json'
                break;
            case 9970:
                downloadName = 'noCache.json'
                break;
        }
        link.download = downloadName;
        // 注意这里第一个参数是数组
        let blob = new Blob([JSON.stringify(tmp)], {type: 'application/json'});
        link.href = URL.createObjectURL(blob);
        link.click();
        //手动释放掉 防止占用内存
        URL.revokeObjectURL(link.href);
    }

/*
    function computeDelay(mode){
        // let curTime = new Date().getTime()
        // curTime -= $scope.requestLayBack

        let requestListLength = $scope.requestList.length
        let reqIdx = requestListLength - 1

        if($scope.requestList.length<=0){
            return
        }

        if($scope.pause_flag!==1) {
            console.log($scope.requestList)
        }

            // trequest：客户端发送HTTP请求的时间点；
            // tresponse：客户端接收到HTTP响应的第一个字节的时间点；
            // _tfinish：客户端接收完HTTP响应的最后一个字节的时间点，即请求完成时间

        while(requestListLength>0 && reqIdx>=0){

            let requestStartTime = $scope.requestList[reqIdx].trequest.getTime();
            let requestFirstResponseTime  = $scope.requestList[reqIdx].tresponse.getTime();
            let responseFinishTime = $scope.requestList[reqIdx]._tfinish.getTime();

            let delay = responseFinishTime - requestStartTime
            //console.log(dateFormat(curTime),delay);
            reqIdx--;
        }

    }
    */

    function dateFormat(timestamp){
        return new Date(+timestamp+8*3600*1000).toISOString()
            .replace(/T/,' ')
            .replace(/\..+/,'')
    }

    // Compute total throughput according to recent HTTP requests (Total data in ONE second)
    function computetotalThroughput() {
        const precurTime = new Date().getTime();  // Get current time
        const curTime = precurTime - $scope.requestLayBack;
        let TotalDataInAnInterval = 0;  // Byte
        let TotalTimeInAnInterval = $scope.requestDuration;  // ms
        let requestListLength = $scope.requestList.length;
        let requestListIndex = requestListLength - 1;
        let requestTimeIndex = curTime;
        while (requestListLength > 0 && requestListIndex >= 0) {
            let requestFinishTime = $scope.requestList[requestListIndex]._tfinish.getTime();
            let requestResponseTime  = $scope.requestList[requestListIndex].tresponse.getTime();

            if (requestFinishTime > curTime - $scope.requestDuration && requestResponseTime < curTime) {
                // Accumulate the downloaded data (Byte)
                let requestDownloadBytes = $scope.requestList[requestListIndex].trace.reduce((a, b) => a + b.b[0], 0);
                if (requestResponseTime > curTime - $scope.requestDuration) {
                    if (requestFinishTime <= curTime) {
                        TotalDataInAnInterval += requestDownloadBytes;
                    } else {
                        TotalDataInAnInterval += ( requestDownloadBytes * ( ( curTime - requestResponseTime ) / ( requestFinishTime - requestResponseTime ) ) );
                    }
                } else {
                    if (requestFinishTime <= curTime) {
                        TotalDataInAnInterval += ( requestDownloadBytes * ( ( requestFinishTime - (curTime - $scope.requestDuration) ) / ( requestFinishTime - requestResponseTime ) ) );
                    } else {
                        TotalDataInAnInterval += ( requestDownloadBytes * ( $scope.requestDuration / ( requestFinishTime - requestResponseTime ) ) );
                    }
                }
                // Subtract the free time (ms)
                if (requestTimeIndex > requestFinishTime) {
                    TotalTimeInAnInterval -= (requestTimeIndex - requestFinishTime);
                }
                // More the time index forward
                if (requestTimeIndex > requestResponseTime) {
                    requestTimeIndex = requestResponseTime;
                }
            }
            requestListIndex--;
        }


        if (curTime - $scope.requestDuration < requestTimeIndex) {
            TotalTimeInAnInterval -= (requestTimeIndex - (curTime - $scope.requestDuration));
        }

        if (TotalDataInAnInterval != 0 && TotalTimeInAnInterval != 0) {
            $scope.totalThroughput = Math.round((8 * TotalDataInAnInterval) / (TotalTimeInAnInterval / 1000));  // bps
        }

        $scope.totalThroughput = localStorage.getItem('throunghput');
        //console.log('total throughput', $scope.totalThroughput)
    }

    // Compute QoE
    function computeQoE() {
        if ($scope.playerPastDownloadingQuality.length == 0 || $scope.playerDownloadingQuality.length == 0) {
            $scope.totalQOE = NaN;
            $scope.viewerQOE = NaN;
            $scope.contentQOE = NaN;
            $scope.playerPastDownloadingQuality = $scope.playerDownloadingQuality;
             return
        }

        let pretotalQOE = 0;  // = Quality - miu * Stalls - lambda * Quality switches
        let previewerQOE = 0;  // = FOVScore * (Quality - miu * Stalls - lambda * Quality switches)
        let precontentQOE = 0;  // = FOVScore * ContentScore * (Quality - miu * Stalls - lambda * Quality switches + omega * Content score)

        for (let i = 0; i < $scope.playerCount; i++) {

            // Compute divation between angle of view and location of tile
            let playerSettings = $scope.players[i].getSettings().info;

            //球面坐标系中 r是半径
            let r = Math.sqrt(playerSettings.location.x * playerSettings.location.x + playerSettings.location.y * playerSettings.location.y + playerSettings.location.z * playerSettings.location.z);

            let tile_theta = Math.acos(playerSettings.location.y / (r == 0 ? 1 : r));
            let tile_phi = Math.atan(playerSettings.location.x / (playerSettings.location.z == 0 ? 1 : playerSettings.location.z));

            let view_theta = (90 - $scope.lat) * (Math.PI / 180);
            let view_phi = (270 - $scope.lon >= 0 ? 270 - $scope.lon : 270 - $scope.lon + 360) * (Math.PI / 180);

            let tile_z = Math.sin(tile_theta) * Math.cos(tile_phi);
            tile_z = playerSettings.location.z < 0 ? tile_z < 0 ? tile_z : -tile_z : tile_z;

            let tile_x = Math.sin(tile_theta) * Math.sin(tile_phi);
            let tile_y = Math.cos(tile_theta);

            let view_x = Math.sin(view_theta) * Math.sin(view_phi);
            let view_y = Math.cos(view_theta);
            let view_z = Math.sin(view_theta) * Math.cos(view_phi);


            //弧度化为角度
            $scope.playerDivation[i] = Math.acos((tile_z * view_z + tile_x * view_x + tile_y * view_y) / (Math.sqrt(tile_z * tile_z + tile_x * tile_x + tile_y * tile_y) * Math.sqrt(view_z * view_z + view_x * view_x + view_y * view_y))) * (180 / Math.PI);


            // another version
            /*
            let height = playerSettings.height;

            let tile_1_x = playerSettings.location.x;
            let tile_1_y = playerSettings.location.y;
            let tile_1_z = playerSettings.location.z;

            let tile_2_x = playerSettings.location.x;
            let tile_2_y = playerSettings.location.y;
            let tile_2_z = playerSettings.location.z;

            let tile_3_x = playerSettings.location.x;
            let tile_3_y = playerSettings.location.y;
            let tile_3_z = playerSettings.location.z;

            let tile_4_x = playerSettings.location.x;
            let tile_4_y = playerSettings.location.y;
            let tile_4_z = playerSettings.location.z;

            if(Math.abs(playerSettings.location.x) == height / 2){
                tile_1_x = playerSettings.location.x;
                tile_1_y = playerSettings.location.y + height / 2;
                tile_1_z = playerSettings.location.z + height / 2;
                tile_2_x = playerSettings.location.x;
                tile_2_y = playerSettings.location.y - height / 2;
                tile_2_z = playerSettings.location.z - height / 2;
                tile_3_x = playerSettings.location.x;
                tile_3_y = playerSettings.location.y + height / 2;
                tile_3_z = playerSettings.location.z - height / 2;
                tile_4_x = playerSettings.location.x;
                tile_4_y = playerSettings.location.y - height / 2;
                tile_4_z = playerSettings.location.z + height / 2;
            }else if(Math.abs(playerSettings.location.y) == height / 2){
                tile_1_x = playerSettings.location.x + height / 2;
                tile_1_y = playerSettings.location.y;
                tile_1_z = playerSettings.location.z + height / 2;
                tile_2_x = playerSettings.location.x - height / 2;
                tile_2_y = playerSettings.location.y;
                tile_2_z = playerSettings.location.z - height / 2;
                tile_3_x = playerSettings.location.x + height / 2;
                tile_3_y = playerSettings.location.y;
                tile_3_z = playerSettings.location.z - height / 2;
                tile_4_x = playerSettings.location.x - height / 2;
                tile_4_y = playerSettings.location.y;
                tile_4_z = playerSettings.location.z + height / 2;
            }else{
                tile_1_x = playerSettings.location.x + height / 2;
                tile_1_y = playerSettings.location.y + height / 2;
                tile_1_z = playerSettings.location.z;
                tile_2_x = playerSettings.location.x - height / 2;
                tile_2_y = playerSettings.location.y - height / 2;
                tile_2_z = playerSettings.location.z;
                tile_3_x = playerSettings.location.x + height / 2;
                tile_3_y = playerSettings.location.y - height / 2;
                tile_3_z = playerSettings.location.z;
                tile_4_x = playerSettings.location.x - height / 2;
                tile_4_y = playerSettings.location.y + height / 2;
                tile_4_z = playerSettings.location.z;
            }
            let tile_5_x = playerSettings.location.x;
            let tile_5_y = playerSettings.location.y;
            let tile_5_z = playerSettings.location.z;

            // select tile in Fov
            let Divation_1=Math.acos((tile_1_z * view_z + tile_1_x * view_x + tile_1_y * view_y) / (Math.sqrt(tile_1_z * tile_1_z + tile_1_x * tile_1_x + tile_1_y * tile_1_y) * Math.sqrt(view_z * view_z + view_x * view_x + view_y * view_y))) * (180 / Math.PI);
            let Divation_2=Math.acos((tile_2_z * view_z + tile_2_x * view_x + tile_2_y * view_y) / (Math.sqrt(tile_2_z * tile_2_z + tile_2_x * tile_2_x + tile_2_y * tile_2_y) * Math.sqrt(view_z * view_z + view_x * view_x + view_y * view_y))) * (180 / Math.PI);
            let Divation_3=Math.acos((tile_3_z * view_z + tile_3_x * view_x + tile_3_y * view_y) / (Math.sqrt(tile_3_z * tile_3_z + tile_3_x * tile_3_x + tile_3_y * tile_3_y) * Math.sqrt(view_z * view_z + view_x * view_x + view_y * view_y))) * (180 / Math.PI);
            let Divation_4=Math.acos((tile_4_z * view_z + tile_4_x * view_x + tile_4_y * view_y) / (Math.sqrt(tile_4_z * tile_4_z + tile_4_x * tile_4_x + tile_4_y * tile_4_y) * Math.sqrt(view_z * view_z + view_x * view_x + view_y * view_y))) * (180 / Math.PI);
            let Divation_5=Math.acos((tile_5_z * view_z + tile_5_x * view_x + tile_5_y * view_y) / (Math.sqrt(tile_5_z * tile_5_z + tile_5_x * tile_5_x + tile_5_y * tile_5_y) * Math.sqrt(view_z * view_z + view_x * view_x + view_y * view_y))) * (180 / Math.PI);
            console.log("顶点1角度"+Divation_1)
            console.log("顶点2角度"+Divation_2)
            console.log("顶点3角度"+Divation_3)
            console.log("顶点4角度"+Divation_4)
            console.log("中心角度"+Divation_5)
            if( Divation_1 < 60 || Divation_2 < 60 || Divation_3 < 60 || Divation_4 < 60 || Divation_5 < 60){
                console.log("tile"+playerSettings.face+"在视野里")
                tileinFov.push(1)
            }else{
                console.log("tile"+playerSettings.face+"不在视野里")
                tileinFov.push(0)
            }
            console.log(tileinFov)
            $scope.tilesinFov.push(tileinFov)
            console.log($scope.tilesinFov)

             */
        }



        for (let i = 0; i < $scope.playerCount; i++) {
            // Computing FOV score
            $scope.playerFOVScore[i] = 100 * (($scope.playerDivation[i] - Math.min.apply(Math, $scope.playerDivation)) / (Math.max.apply(Math,$scope.playerDivation) - Math.min.apply(Math,$scope.playerDivation)));
            // Computing content score
            let info = $scope.players[i].getSettings().info;
            if ($scope.ssresults) {
                // gains from current segment's level
                let currentTime = parseInt($scope.playerTime[i] + $scope.playerBufferLength[i]);
                let currentIndex = currentTime / info.duration + 1;
                let currentIndexString = info.face.toString() + "_" + (info.row * $scope.contents.col + info.col).toString() + "_" + currentIndex.toString();
                if ($scope.ssresults[currentIndexString] != NaN && $scope.ssresults['maximum'] != NaN && $scope.ssresults['minimum'] != NaN) {
                    let currentResult = $scope.ssresults[currentIndexString];
                    let MaximumResult = $scope.ssresults['maximum'];
                    let MinimumResult = $scope.ssresults['minimum'];
                    let RankingResult = (currentResult - MinimumResult) / (MaximumResult - MinimumResult);
                    // gains from tile's level
                    let curTileIndexString = info.face.toString() + "_" + (info.row * $scope.contents.col + info.col).toString();
                    if ($scope.ssresults[curTileIndexString] != NaN || $scope.ssresults['average'] != NaN) {
                        let curTileResult = $scope.ssresults[curTileIndexString];
                        let AverageResult = $scope.ssresults['average'];
                        if (curTileResult >= AverageResult) {
                            RankingResult = Math.min(RankingResult + $scope.content_curTile_bias, 1);
                        } else {
                            RankingResult = Math.max(RankingResult - $scope.content_curTile_bias, 0);
                        }
                    }
                    $scope.playerContentScore[i] = RankingResult.toFixed(2) * 100;
                }
            }
            ////////////////////////////////// Regardless of stall, only totalQOE //////////////////////////////////
            if( $scope.pause_flag == 1 ){
                var pausetime_bysec = new Date().getTime() - $scope.pause_time;
                pausetime_bysec = pausetime_bysec * 0.001;
               // console.log("距离上一次暂停的时长"+pausetime_bysec);
                if(pausetime_bysec>=1){
                    $scope.rebuffer_delay = 1;
                }else{
                    $scope.rebuffer_delay = pausetime_bysec;
                }

            }else{
                var playtime_bysec = new Date().getTime() - $scope.pause_time - $scope.lastpause_time;
                playtime_bysec = playtime_bysec * 0.001;
                if(playtime_bysec < 1){
                    $scope.rebuffer_delay = 1 - playtime_bysec;
                }else{
                    $scope.rebuffer_delay = 0;
                }
            }
            // console.log("是否卡顿"+$scope.pause_flag);
            // console.log("卡顿时间"+$scope.rebuffer_delay);
            switch ($scope.qQOE) {
                case 'linear':
                    pretotalQOE = pretotalQOE + (1-$scope.rebuffer_delay)*(($scope.playerBitrateList[i][$scope.playerDownloadingQuality[i]].bitrate - $scope.playerBitrateList[i][0].bitrate)
                                              - $scope.lambdaQOE * Math.abs($scope.playerBitrateList[i][$scope.playerDownloadingQuality[i]].bitrate - $scope.playerBitrateList[i][$scope.playerPastDownloadingQuality[i]].bitrate));
                    previewerQOE = previewerQOE + (1-$scope.rebuffer_delay)*($scope.playerFOVScore[i] * (($scope.playerBitrateList[i][$scope.playerDownloadingQuality[i]].bitrate - $scope.playerBitrateList[i][0].bitrate) - $scope.lambdaQOE * Math.abs($scope.playerBitrateList[i][$scope.playerDownloadingQuality[i]].bitrate - $scope.playerBitrateList[i][$scope.playerPastDownloadingQuality[i]].bitrate)));
                    precontentQOE = precontentQOE + (1-$scope.rebuffer_delay)*($scope.playerFOVScore[i] * $scope.playerContentScore[i] * (($scope.playerBitrateList[i][$scope.playerDownloadingQuality[i]].bitrate - $scope.playerBitrateList[i][0].bitrate) - $scope.lambdaQOE * Math.abs($scope.playerBitrateList[i][$scope.playerDownloadingQuality[i]].bitrate - $scope.playerBitrateList[i][$scope.playerPastDownloadingQuality[i]].bitrate)));
                    break;
                case 'log':
                    pretotalQOE = pretotalQOE + (1-$scope.rebuffer_delay)*(Math.log(($scope.playerBitrateList[i][$scope.playerDownloadingQuality[i]].bitrate - $scope.playerBitrateList[i][0].bitrate) + 1)
                                              - $scope.lambdaQOE * Math.abs(Math.log($scope.playerBitrateList[i][$scope.playerDownloadingQuality[i]].bitrate + 1) - Math.log($scope.playerBitrateList[i][$scope.playerPastDownloadingQuality[i]].bitrate + 1)));
                    previewerQOE = previewerQOE + (1-$scope.rebuffer_delay)*($scope.playerFOVScore[i] * (Math.log(($scope.playerBitrateList[i][$scope.playerDownloadingQuality[i]].bitrate - $scope.playerBitrateList[i][0].bitrate) + 1) - $scope.lambdaQOE * Math.abs(Math.log($scope.playerBitrateList[i][$scope.playerDownloadingQuality[i]].bitrate + 1) - Math.log($scope.playerBitrateList[i][$scope.playerPastDownloadingQuality[i]].bitrate + 1))));
                    precontentQOE = precontentQOE + (1-$scope.rebuffer_delay)*($scope.playerFOVScore[i] * $scope.playerContentScore[i] * (Math.log(($scope.playerBitrateList[i][$scope.playerDownloadingQuality[i]].bitrate - $scope.playerBitrateList[i][0].bitrate) + 1) - $scope.lambdaQOE * Math.abs(Math.log($scope.playerBitrateList[i][$scope.playerDownloadingQuality[i]].bitrate + 1) - Math.log($scope.playerBitrateList[i][$scope.playerPastDownloadingQuality[i]].bitrate + 1))));
                    break;
                default:
                    break;
            }
        }
        $scope.totalQOE = pretotalQOE;
        $scope.totalQOE_video = ($scope.countTime*$scope.totalQOE_video + $scope.totalQOE) / ($scope.countTime + 1);
        $scope.viewerQOE = previewerQOE;
        $scope.contentQOE = precontentQOE;
        $scope.playerPastDownloadingQuality = $scope.playerDownloadingQuality;
        $scope.countTime += 1;

        if($scope.pause_flag===1){
            $scope.pause_flagbytext.push($scope.pause_flag);  // Data from monitor
            $scope.pause_flagbytext.push("\n");
        }

        else if($scope.pause_flag==0) {
            //record info every x seconds

            $scope.bitrateInfobytext.push(getCurrentBitrateList())
            $scope.bitrateInfobytext.push("\n");
            //console.log($scope.bitrateInfobytext)

            if ($scope.contents.audio && $scope.contents.audio != "")
            {
                $scope.playerDownloadingQualitybytext.push(copy($scope.playerDownloadingQuality.slice(0,-1)));
            }  // Data from monitor
            else{
                $scope.playerDownloadingQualitybytext.push(copy($scope.playerDownloadingQuality));
            }
            $scope.playerDownloadingQualitybytext.push("\n");

            $scope.playerBufferLengthbytext.push(copy($scope.playerBufferLength));  // Data from monitor
            $scope.playerBufferLengthbytext.push("\n");

            $scope.pause_totalbytext.push($scope.pause_total);  // Data from monitor
            $scope.pause_totalbytext.push("\n");

            $scope.rebuffer_timebytext.push($scope.rebuffer_time);  // Data from monitor
            $scope.rebuffer_timebytext.push("\n");

            $scope.playerAverageThroughputbytext.push(copy($scope.playerAverageThroughput))
            $scope.playerAverageThroughputbytext.push('\n')

            $scope.pause_flagbytext.push($scope.pause_flag);  // Data from monitor
            $scope.pause_flagbytext.push("\n");


            console.log('偏离角', $scope.playerDivation)
            let temp = $scope.playerDivation.map(item => {
                return item > $scope.diviationThreshold ? 0 : 1
            })
            $scope.tileRecord.push(temp)
            $scope.tileRecord.push("\n")
            console.log('fov',temp)

            // console.log('downloadingQuality',$scope.playerDownloadingQualitybytext)
            // console.log('playerBuffer',$scope.playerBufferLengthbytext)
            // console.log('pause flag',$scope.pause_flagbytext)
            // console.log('pause total',$scope.pause_totalbytext)
            // console.log('rebuffer time',$scope.rebuffer_timebytext)
            // console.log('throughput',$scope.playerAverageThroughputbytext)
            // console.log('tiles',$scope.tileRecord)
        }
    }

    function getCurrentBitrateList(){
        let temp = []
        for(let i=0;i<$scope.playerCount;i++){
            let separate = $scope.playerBitrateList[i][$scope.playerDownloadingQuality[i]].bitrate
            //console.log(`bitrate for player ${i}: ${separate}`)
            temp.push(separate)
        }
        console.log(temp)
        return temp
    }

    /*
    实现一个深拷贝
    也可以用JSON.parse(JSON.stringify(raw))
     */
    function copy(raw){
        let temp = []
        for(let i=0;i<raw.length;i++){
            temp[i] = raw[i]
        }
        return temp
    }
    // Show the data in monitor
    function updateStats() {
        $scope.stats.splice(0, $scope.stats.length);
        for (let i = 0; i <= $scope.playerCount; i++) {
            if(i == $scope.playerCount) {
                if ($scope.contents.audio && $scope.contents.audio != "") {
                    $scope.playerBufferLength[i] = $scope.players[i].getBufferLength("audio");
                    $scope.playerAverageThroughput[i] = $scope.players[i].getAverageThroughput("audio");
                    $scope.playerTime[i] = $scope.players[i].time();
                    $scope.playerDownloadingQuality[i] = $scope.players[i].getQualityFor("audio");
                    $scope.stats.push({
                        playerid : "audio",
                        bufferlevel : $scope.playerBufferLength[i].toFixed(2) + " s",
                        throughput : $scope.playerAverageThroughput[i].toFixed(0)+ " bps",
                        time : $scope.playerTime[i].toFixed(2) + " s",
                        quality : $scope.players[i].getQualityFor("audio").toFixed(0),
                        fovscore : NaN,
                        playerContentScore : NaN,
                        totaltime : ($scope.playerBufferLength[i] + $scope.playerTime[i]).toFixed(2) + " s",
                        playerCatchUp : ($scope.playerCatchUp[$scope.i] ? "同步中" : "已同步")
                    });
                }
            } else {
                if (i < $scope.playerCount && $scope.playerBitrateList[i].length == 0) {
                    $scope.playerBitrateList[i] = $scope.players[i].getBitrateInfoListFor("video");
                }
                $scope.playerBufferLength[i] = $scope.players[i].getBufferLength("video");
                $scope.playerAverageThroughput[i] = $scope.players[i].getAverageThroughput("video");
                $scope.playerTime[i] = $scope.players[i].time();
                $scope.playerDownloadingQuality[i] = $scope.players[i].getQualityFor("video");
                $scope.stats.push({
                    playerid : "video_" + i,
                    bufferlevel : $scope.playerBufferLength[i].toFixed(2) + " s",
                    throughput : $scope.playerAverageThroughput[i].toFixed(0)+ " bps",
                    time : $scope.playerTime[i].toFixed(2) + " s",
                    quality : $scope.playerDownloadingQuality[i].toFixed(0),
                    fovscore : $scope.playerFOVScore[i].toFixed(0),
                    playerContentScore : $scope.playerContentScore[i].toFixed(0),
                    totaltime : ($scope.playerBufferLength[i] + $scope.playerTime[i]).toFixed(2) + " s",
                    playerCatchUp : ($scope.playerCatchUp[i] ? "同步中" : "已同步")
                });
            }
        }
    }

    // Show the data in figures
    function updateFigures() {
        if($scope.pause_flag===1)
        {
            return
        }
        let time = getTimeForPlot();
        for (let i = 0; i < $scope.playerCount; i++) {
            //$.plot(plotArea, scope.dataset, scope.options)
            $scope.plotPoint("video_" + i, 'quality', $scope.playerDownloadingQuality[i], time);
            $scope.plotPoint("video_" + i, 'buffer', $scope.playerBufferLength[i], time);
            $scope.plotPoint("video_" + i, 'throughput', $scope.playerAverageThroughput[i], time);
        }
        if ($scope.contents.audio && $scope.contents.audio != "") {
            $scope.plotPoint("audio", 'quality', $scope.playerDownloadingQuality[$scope.playerCount], time);
            $scope.plotPoint("audio", 'buffer', $scope.playerBufferLength[$scope.playerCount], time);
            $scope.plotPoint("audio", 'throughput', $scope.playerAverageThroughput[$scope.playerCount], time);
        }
    }
    function getTimeForPlot() {
        let now = new Date().getTime() / 1000;
        return Math.max(now - $scope.startupTime / 1000, 0);
    }


    // Enable the FOV event listener in iframe
    document.getElementById('frame').onload = function () {
        document.getElementById('frame').contentDocument.addEventListener( 'pointerdown', onPointerDown );
    }

    function onPointerDown( event ) {
        if ( event.isPrimary === false ) return;
        $scope.pointerX = event.clientX;
        $scope.pointerY = event.clientY;
        document.getElementById('frame').contentDocument.addEventListener( 'pointermove', onPointerMove );
        document.getElementById('frame').contentDocument.addEventListener( 'pointerup', onPointerUp );
        // console.log("Pointer downs. lon: "+ $scope.lon + "; lat: " + $scope.lat + ".");
    }

    function onPointerMove( event ) {
        if ( event.isPrimary === false ) return;
        $scope.lon += ( event.clientX - $scope.pointerX ) * $scope.rotateRatio;  // In Chrome, turn right then the lon 经度 increases.
        $scope.lon > 360 ? $scope.lon = $scope.lon - 360 : null;
        $scope.lon < 0 ? $scope.lon = $scope.lon + 360 : null;
        $scope.lat -= ( event.clientY - $scope.pointerY ) * $scope.rotateRatio;  // In Chrome, turn up then the lat 纬度 increases.
        $scope.lat > 90 ? $scope.lat = 90 : null;
        $scope.lat < -90 ? $scope.lat = -90 : null;
        $scope.pointerX = event.clientX;
        $scope.pointerY = event.clientY;
        //console.log("Pointer moves. lon: "+ $scope.lon + "; lat: " + $scope.lat + ".");
    }

    function onPointerUp() {
        if ( event.isPrimary === false ) return;
        document.getElementById('frame').contentDocument.removeEventListener( 'pointermove', onPointerMove );
        document.getElementById('frame').contentDocument.removeEventListener( 'pointerup', onPointerUp );
        // console.log("Pointer ups. lon: "+ $scope.lon + "; lat: " + $scope.lat + ".");
    }


}]
);
